package com.sky.skyopsserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sky.skyopsserver.domain.Application;
import com.sky.skyopsserver.domain.Project;
import com.sky.skyopsserver.enums.ResponseCodeEnum;
import com.sky.skyopsserver.exception.BizException;
import com.sky.skyopsserver.mapper.ApplicationMapper;
import com.sky.skyopsserver.mapper.ProjectMapper;
import com.sky.skyopsserver.service.ApplicationService;
import com.sky.skyopsserver.vos.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 应用信息服务实现类
 * 
 * @author Administrator
 * @description 针对表【application(应用信息表)】的数据库操作Service实现
 * @createDate 2025-09-13 17:43:04
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ApplicationServiceImpl extends ServiceImpl<ApplicationMapper, Application>
        implements ApplicationService {

    private final ProjectMapper projectMapper;

    private static final Pattern CODE_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9_-]*$");

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addApplication(ApplicationAddReqVO reqVO) {
        log.info("开始添加应用，编码: {}, 名称: {}", reqVO.getCode(), reqVO.getName());
        
        // 验证应用编码格式
        if (!validateApplicationCode(reqVO.getCode())) {
            throw new BizException(ResponseCodeEnum.APPLICATION_CODE_INVALID);
        }
        
        // 检查应用编码是否已存在
        if (checkApplicationCodeExists(reqVO.getCode(), null)) {
            throw new BizException(ResponseCodeEnum.APPLICATION_CODE_EXISTS);
        }
        
        // 检查应用名称是否已存在
        if (checkApplicationNameExists(reqVO.getName(), null)) {
            throw new BizException(ResponseCodeEnum.APPLICATION_NAME_EXISTS);
        }
        
        // 检查项目是否存在
        Project project = projectMapper.selectById(reqVO.getProjectId());
        if (Objects.isNull(project)) {
            throw new BizException(ResponseCodeEnum.APPLICATION_PROJECT_NOT_EXISTS);
        }
        
        // 构建应用实体
        Application application = new Application();
        BeanUtils.copyProperties(reqVO, application);
        application.setProjectName(project.getName());
        application.setCreateTime(LocalDateTime.now());
        
        // 保存到数据库
        boolean saved = save(application);
        if (!saved) {
            throw new BizException(ResponseCodeEnum.APPLICATION_ADD_FAILED);
        }
        
        log.info("应用添加成功，应用ID: {}", application.getId());
        return application.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateApplication(ApplicationUpdateReqVO reqVO) {
        log.info("开始更新应用，应用ID: {}", reqVO.getId());
        
        // 检查应用是否存在
        Application existingApplication = getById(reqVO.getId());
        if (Objects.isNull(existingApplication)) {
            throw new BizException(ResponseCodeEnum.APPLICATION_NOT_EXISTS);
        }
        
        // 验证应用编码格式
        if (!validateApplicationCode(reqVO.getCode())) {
            throw new BizException(ResponseCodeEnum.APPLICATION_CODE_INVALID);
        }
        
        // 检查应用编码是否已存在（排除当前应用）
        if (checkApplicationCodeExists(reqVO.getCode(), reqVO.getId())) {
            throw new BizException(ResponseCodeEnum.APPLICATION_CODE_EXISTS);
        }
        
        // 检查应用名称是否已存在（排除当前应用）
        if (checkApplicationNameExists(reqVO.getName(), reqVO.getId())) {
            throw new BizException(ResponseCodeEnum.APPLICATION_NAME_EXISTS);
        }
        
        // 检查项目是否存在
        Project project = projectMapper.selectById(reqVO.getProjectId());
        if (Objects.isNull(project)) {
            throw new BizException(ResponseCodeEnum.APPLICATION_PROJECT_NOT_EXISTS);
        }
        
        // 更新应用信息
        Application application = new Application();
        BeanUtils.copyProperties(reqVO, application);
        application.setProjectName(project.getName());
        
        boolean updated = updateById(application);
        if (!updated) {
            throw new BizException(ResponseCodeEnum.APPLICATION_UPDATE_FAILED);
        }
        
        log.info("应用更新成功，应用ID: {}", reqVO.getId());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteApplication(Long id) {
        log.info("开始删除应用，应用ID: {}", id);
        
        // 检查应用是否存在
        Application existingApplication = getById(id);
        if (Objects.isNull(existingApplication)) {
            throw new BizException(ResponseCodeEnum.APPLICATION_NOT_EXISTS);
        }
        
        boolean deleted = removeById(id);
        if (!deleted) {
            throw new BizException(ResponseCodeEnum.APPLICATION_DELETE_FAILED);
        }
        
        log.info("应用删除成功，应用ID: {}", id);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchDeleteApplication(List<Long> ids) {
        log.info("开始批量删除应用，应用ID列表: {}", ids);
        
        if (CollectionUtils.isEmpty(ids)) {
            throw new BizException(ResponseCodeEnum.PARAM_NOT_VALID);
        }
        
        // 检查所有应用是否存在
        List<Application> existingApplications = listByIds(ids);
        if (existingApplications.size() != ids.size()) {
            throw new BizException(ResponseCodeEnum.APPLICATION_NOT_EXISTS);
        }
        
        boolean deleted = removeByIds(ids);
        if (!deleted) {
            throw new BizException(ResponseCodeEnum.APPLICATION_DELETE_FAILED);
        }
        
        log.info("应用批量删除成功，删除数量: {}", ids.size());
        return true;
    }

    @Override
    public ApplicationRspVO getApplicationById(Long id) {
        log.info("查询应用详情，应用ID: {}", id);
        
        Application application = getById(id);
        if (Objects.isNull(application)) {
            throw new BizException(ResponseCodeEnum.APPLICATION_NOT_EXISTS);
        }
        
        return convertToRspVO(application);
    }

    @Override
    public ApplicationRspVO getApplicationByCode(String code) {
        log.info("根据编码查询应用，应用编码: {}", code);
        
        Application application = getOne(new LambdaQueryWrapper<Application>()
                .eq(Application::getCode, code));
        
        if (Objects.isNull(application)) {
            throw new BizException(ResponseCodeEnum.APPLICATION_NOT_EXISTS);
        }
        
        return convertToRspVO(application);
    }

    @Override
    public IPage<ApplicationRspVO> getApplicationPage(ApplicationPageReqVO reqVO) {
        log.info("分页查询应用列表，查询条件: {}", reqVO);
        
        // 构建分页对象
        Page<Application> page = new Page<>(reqVO.getCurrent(), reqVO.getSize());
        
        // 构建查询条件
        LambdaQueryWrapper<Application> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasText(reqVO.getCode()), Application::getCode, reqVO.getCode())
                   .like(StringUtils.hasText(reqVO.getName()), Application::getName, reqVO.getName())
                   .like(StringUtils.hasText(reqVO.getRemark()), Application::getRemark, reqVO.getRemark())
                   .like(StringUtils.hasText(reqVO.getProjectName()), Application::getProjectName, reqVO.getProjectName())
                   .eq(Objects.nonNull(reqVO.getProjectId()), Application::getProjectId, reqVO.getProjectId())
                   .orderByDesc(Application::getCreateTime);
        
        // 执行分页查询
        IPage<Application> applicationPage = page(page, queryWrapper);
        
        // 转换为响应VO
        IPage<ApplicationRspVO> rspPage = applicationPage.convert(this::convertToRspVO);
        
        log.info("分页查询应用列表完成，总记录数: {}", rspPage.getTotal());
        return rspPage;
    }

    /**
     * 转换为响应VO
     * 
     * @param application 应用实体
     * @return 响应VO
     */
    private ApplicationRspVO convertToRspVO(Application application) {
        ApplicationRspVO rspVO = new ApplicationRspVO();
        BeanUtils.copyProperties(application, rspVO);
        return rspVO;
    }

    /**
     * 转换为选项响应VO
     * 
     * @param application 应用实体
     * @return 选项响应VO
     */
    private ApplicationOptionRspVO convertToOptionRspVO(Application application) {
        ApplicationOptionRspVO optionVO = new ApplicationOptionRspVO();
        BeanUtils.copyProperties(application, optionVO);
        return optionVO;
    }

    @Override
    public List<ApplicationOptionRspVO> getAllApplicationOptions() {
        log.info("查询所有应用选项");
        
        List<Application> applications = list(new LambdaQueryWrapper<Application>()
                .orderByAsc(Application::getName));
        
        return applications.stream()
                .map(this::convertToOptionRspVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<ApplicationOptionRspVO> getApplicationOptionsByProjectId(Long projectId) {
        log.info("根据项目ID查询应用选项，项目ID: {}", projectId);
        
        List<Application> applications = list(new LambdaQueryWrapper<Application>()
                .eq(Application::getProjectId, projectId)
                .orderByAsc(Application::getName));
        
        return applications.stream()
                .map(this::convertToOptionRspVO)
                .collect(Collectors.toList());
    }

    @Override
    public ApplicationStatisticsRspVO getApplicationStatistics() {
        log.info("获取应用统计信息");
        
        // 应用总数
        long totalCount = count();
        
        // 项目总数
        long totalProjectCount = projectMapper.selectCount(null);
        
        // 有应用的项目数量
        List<Long> projectIdsWithApps = getProjectIdsWithApplications();
        long projectsWithAppsCount = projectIdsWithApps.size();
        
        // 空项目数量
        long emptyProjectsCount = totalProjectCount - projectsWithAppsCount;
        
        // 时间统计
        LocalDateTime today = LocalDateTime.now().with(LocalTime.MIN);
        LocalDateTime weekStart = today.minusDays(today.getDayOfWeek().getValue() - 1);
        LocalDateTime monthStart = today.withDayOfMonth(1);
        
        long todayAddedCount = count(new LambdaQueryWrapper<Application>()
                .ge(Application::getCreateTime, today));
        
        long weeklyAddedCount = count(new LambdaQueryWrapper<Application>()
                .ge(Application::getCreateTime, weekStart));
        
        long monthlyAddedCount = count(new LambdaQueryWrapper<Application>()
                .ge(Application::getCreateTime, monthStart));
        
        // 平均每项目应用数
        double avgAppsPerProject = totalProjectCount > 0 ? (double) totalCount / totalProjectCount : 0.0;
        
        return ApplicationStatisticsRspVO.builder()
                .totalCount(totalCount)
                .totalProjectCount(totalProjectCount)
                .projectsWithAppsCount(projectsWithAppsCount)
                .emptyProjectsCount(emptyProjectsCount)
                .todayAddedCount(todayAddedCount)
                .weeklyAddedCount(weeklyAddedCount)
                .monthlyAddedCount(monthlyAddedCount)
                .avgAppsPerProject(Math.round(avgAppsPerProject * 100.0) / 100.0)
                .build();
    }

    @Override
    public Boolean checkApplicationCodeExists(String code, Long excludeId) {
        LambdaQueryWrapper<Application> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Application::getCode, code);
        if (Objects.nonNull(excludeId)) {
            queryWrapper.ne(Application::getId, excludeId);
        }
        return count(queryWrapper) > 0;
    }

    @Override
    public Boolean checkApplicationNameExists(String name, Long excludeId) {
        LambdaQueryWrapper<Application> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Application::getName, name);
        if (Objects.nonNull(excludeId)) {
            queryWrapper.ne(Application::getId, excludeId);
        }
        return count(queryWrapper) > 0;
    }

    @Override
    public List<ApplicationRspVO> searchApplicationByName(String name) {
        log.info("根据名称模糊查询应用，名称关键字: {}", name);
        
        List<Application> applications = list(new LambdaQueryWrapper<Application>()
                .like(Application::getName, name)
                .orderByAsc(Application::getName));
        
        return applications.stream()
                .map(this::convertToRspVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<ApplicationRspVO> searchApplicationByCode(String code) {
        log.info("根据编码模糊查询应用，编码关键字: {}", code);
        
        List<Application> applications = list(new LambdaQueryWrapper<Application>()
                .like(Application::getCode, code)
                .orderByAsc(Application::getCode));
        
        return applications.stream()
                .map(this::convertToRspVO)
                .collect(Collectors.toList());
    }

    @Override
    public Boolean validateApplicationCode(String code) {
        return StringUtils.hasText(code) && CODE_PATTERN.matcher(code).matches();
    }

    @Override
    public List<String> getAllApplicationCodes() {
        log.info("获取所有应用编码列表");
        
        List<Application> applications = list(new LambdaQueryWrapper<Application>()
                .select(Application::getCode)
                .orderByAsc(Application::getCode));
        
        return applications.stream()
                .map(Application::getCode)
                .collect(Collectors.toList());
    }

    @Override
    public List<String> getAllApplicationNames() {
        log.info("获取所有应用名称列表");
        
        List<Application> applications = list(new LambdaQueryWrapper<Application>()
                .select(Application::getName)
                .orderByAsc(Application::getName));
        
        return applications.stream()
                .map(Application::getName)
                .collect(Collectors.toList());
    }

    @Override
    public Long getApplicationCountByProjectId(Long projectId) {
        return count(new LambdaQueryWrapper<Application>()
                .eq(Application::getProjectId, projectId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean moveApplicationsToProject(List<Long> applicationIds, Long targetProjectId) {
        log.info("移动应用到项目，应用ID列表: {}, 目标项目ID: {}", applicationIds, targetProjectId);
        
        if (CollectionUtils.isEmpty(applicationIds)) {
            throw new BizException(ResponseCodeEnum.PARAM_NOT_VALID);
        }
        
        // 检查目标项目是否存在
        Project targetProject = projectMapper.selectById(targetProjectId);
        if (Objects.isNull(targetProject)) {
            throw new BizException(ResponseCodeEnum.APPLICATION_PROJECT_NOT_EXISTS);
        }
        
        // 检查所有应用是否存在
        List<Application> applications = listByIds(applicationIds);
        if (applications.size() != applicationIds.size()) {
            throw new BizException(ResponseCodeEnum.APPLICATION_NOT_EXISTS);
        }
        
        // 批量更新项目信息
        applications.forEach(application -> {
            application.setProjectId(targetProjectId);
            application.setProjectName(targetProject.getName());
        });
        
        boolean updated = updateBatchById(applications);
        if (!updated) {
            throw new BizException(ResponseCodeEnum.APPLICATION_UPDATE_FAILED);
        }
        
        log.info("应用移动成功，移动数量: {}", applications.size());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long copyApplicationToProject(Long applicationId, Long targetProjectId, String newCode, String newName) {
        log.info("复制应用到项目，应用ID: {}, 目标项目ID: {}, 新编码: {}, 新名称: {}", 
                applicationId, targetProjectId, newCode, newName);
        
        // 检查原应用是否存在
        Application sourceApplication = getById(applicationId);
        if (Objects.isNull(sourceApplication)) {
            throw new BizException(ResponseCodeEnum.APPLICATION_NOT_EXISTS);
        }
        
        // 检查目标项目是否存在
        Project targetProject = projectMapper.selectById(targetProjectId);
        if (Objects.isNull(targetProject)) {
            throw new BizException(ResponseCodeEnum.APPLICATION_PROJECT_NOT_EXISTS);
        }
        
        // 验证新编码格式
        if (!validateApplicationCode(newCode)) {
            throw new BizException(ResponseCodeEnum.APPLICATION_CODE_INVALID);
        }
        
        // 检查新编码是否已存在
        if (checkApplicationCodeExists(newCode, null)) {
            throw new BizException(ResponseCodeEnum.APPLICATION_CODE_EXISTS);
        }
        
        // 检查新名称是否已存在
        if (checkApplicationNameExists(newName, null)) {
            throw new BizException(ResponseCodeEnum.APPLICATION_NAME_EXISTS);
        }
        
        // 创建新应用
        Application newApplication = new Application();
        BeanUtils.copyProperties(sourceApplication, newApplication);
        newApplication.setId(null); // 清空ID，让数据库自动生成
        newApplication.setCode(newCode);
        newApplication.setName(newName);
        newApplication.setProjectId(targetProjectId);
        newApplication.setProjectName(targetProject.getName());
        newApplication.setCreateTime(LocalDateTime.now());
        
        boolean saved = save(newApplication);
        if (!saved) {
            throw new BizException(ResponseCodeEnum.APPLICATION_ADD_FAILED);
        }
        
        log.info("应用复制成功，新应用ID: {}", newApplication.getId());
        return newApplication.getId();
    }

    @Override
    public List<ApplicationRspVO> getApplicationsByProjectId(Long projectId) {
        log.info("获取项目下的应用列表，项目ID: {}", projectId);
        
        List<Application> applications = list(new LambdaQueryWrapper<Application>()
                .eq(Application::getProjectId, projectId)
                .orderByAsc(Application::getName));
        
        return applications.stream()
                .map(this::convertToRspVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<Long> getEmptyProjectIds() {
        log.info("获取空项目列表");
        
        // 获取所有项目ID
        List<Project> allProjects = projectMapper.selectList(new LambdaQueryWrapper<Project>()
                .select(Project::getId));
        
        // 获取有应用的项目ID
        List<Long> projectIdsWithApps = getProjectIdsWithApplications();
        
        // 过滤出空项目ID
        return allProjects.stream()
                .map(Project::getId)
                .filter(projectId -> !projectIdsWithApps.contains(projectId))
                .collect(Collectors.toList());
    }

    @Override
     public List<Long> getProjectIdsWithApplications() {
         log.info("获取有应用的项目列表");
         
         List<Application> applications = list(new LambdaQueryWrapper<Application>()
                 .select(Application::getProjectId)
                 .groupBy(Application::getProjectId));
         
         return applications.stream()
                 .map(Application::getProjectId)
                 .distinct()
                 .collect(Collectors.toList());
     }
 }




